using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.IO;
using System.Net;
//using EvonyExtension;
//using Frankfort.Threading.Internal;


public enum LocalType
{
    none = 0,
    essential = 1,
    unessential = 2,
}

public class BundleInfo
{
    public string name;
    public string hash;
    public uint size;
    public uint origin_size;
    public uint compress;
//    public LocalType local_type;
    //old property
//    public uint crc;
//    public int version;


    public string GetHashName()
    {
        return name + "_" + hash;
    }

    public static string GetHashName(string name, string hash)
    {
        return name + "_" + hash;
    }

    public static string ConvertToBundleNameAndHash(string fileName, ref string hash)
    {
        int index = fileName.LastIndexOf('_');
        if (index > 0)
        {
            string bundleName = fileName.Substring(0, index);
            hash = fileName.Substring(index + 1);
            return bundleName;
        }

//        string[] arr = fileName.Split('+');
//        if(arr.Length > 1)
//        {
//            string bundleName = arr[0];
//            hash = arr[1];
//            return bundleName;
//        }
        return null;
    }

    public string GetDownloadPath()
    {
        return BundleVersionManager.bundlePath + "/" + GetHashName();
    }
}

public class ServerBundleInfo
{
    public string url;
    public BundleVersionConfig config;
}

public class LocalBundleInfo
{
    public string name;
    public string hash;
    public LocalType local_type;

    public string GetLocalBundlePath()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            return Application.dataPath + "!assets/" + this.GetHashName();
        }
        else
        {
            return Application.streamingAssetsPath + "/" + this.GetHashName();
        }
    }

    public string GetHashName()
    {
        return BundleInfo.GetHashName(name, hash);
    }
}

public class BundleVersionConfig
{
    public string md5;
    public uint size;
    public uint origin_size;
    public uint compress;
    public string build_time;
    public string platform;
    public string compile_type;
    public int version;
    public int min_app_version;
    public int count;
    public bool bundle_name_encoded = true;
    public Dictionary<string, BundleInfo> bundles;



    //old property begin
//    public uint crc;
//    public int max_app_version;

//    public int count;
    //old property end

    public void setTime()
    {
        System.DateTime time = System.DateTime.Now;
        build_time = time.ToString("u");
    }

    public override bool Equals(object obj)
    {
        BundleVersionConfig c = obj as BundleVersionConfig;
        if (c == null)
        {
            return false;
        }

        if (c.version != this.version)
        {
            return false;
        }

        if (c.md5 != this.md5)
        {
            return false;
        }

        return true;
    }
}

public enum DownloadBundleError
{
	None,
	DownloadFailed,
	DecompressFailed,
	DownloadEncodingError,
	DownloadSizeError,
	FileOperationFailed
}
public class DownloadBundleTaskInfo
{
	public delegate void CallBack(DownloadBundleTaskInfo info);

	private HttpRedirectHelper redirectHelper;
	private CallBack callBack;
	private string bundleName;
	private string url;
	private string downloadPath;
	private string decompressPath;
	private BundleInfo bundleInfo;
	private bool needDownload;
	private bool needDecompress;
	private bool downloadFinish;
	private bool decompressFinish;
	private DownloadBundleError error = DownloadBundleError.None;
	private object downloadRequest;
	private object decompressRequest;
	private int decompressRetryCount;
	private CompressManager.DecompressCallback decompressCallBack;

	public DownloadBundleError getError()
	{
		return error;
	}

	public uint size
	{
		get
		{
			return bundleInfo.size;
		}
	}

	public bool isLocalDecopmress
	{
		get
		{
			return !needDownload && !needDecompress;
		}
	}

	public bool isNeedDownload
	{
		get
		{
			return needDownload;
		}
	}
	
	public bool isDownloadComplete
	{
		get
		{
			return downloadFinish;
		}
	}
	
	public bool isNeedDecompress
	{
		get
		{
			return needDecompress;
		}
	}
	
	public bool isDecompressComplete
	{
		get
		{
			return decompressFinish;
		}
	}

	public bool isComplete
	{
		get
		{
			if(!needDownload && !needDecompress)
			{
				return decompressFinish;
			}
			else
			{
				if(needDecompress)
				{
					return decompressFinish;
				}
				else
				{
					return downloadFinish;
				}
			}
		}
	}
	
	public DownloadBundleTaskInfo(string bundleName, BundleInfo info, string downloadUrl, bool needDownload, bool needDecompress)
	{
		this.bundleName = bundleName;
		this.needDownload = needDownload;
		this.needDecompress = needDecompress;
		this.bundleInfo = info;

        string fileName = this.bundleInfo.GetHashName();
        this.url = downloadUrl + "/" + PlatformEx.getPlatform() + "/" + VersionEx.compile_type + "/" + info.GetHashName() + BundleVersionManager.bundleExt2 + "?hash=" + this.bundleInfo.hash + "&size=" + this.bundleInfo.size;
		this.downloadPath = BundleVersionManager.downloadPath + "/" + fileName + BundleVersionManager.bundleExt2;
		this.decompressPath = BundleVersionManager.bundlePath + "/" + fileName + BundleVersionManager.bundleExt2;
	}
	
	public BundleInfo getBundleInfo()
	{
		return this.bundleInfo;
	}
	
	public string getBundleName()
	{
		return this.bundleName;
	}
	
	public int getProgress()
	{
		if(downloadFinish)
		{
			return (int)this.bundleInfo.size;
		}
        return HttpDownloadManager.instance.getRequestProgress(downloadRequest);
	}
	
	public float getSpeed()
	{
		return HttpDownloadManager.instance.getRequestSpeed(downloadRequest);
	}
	
	public uint getTotal()
	{
		return bundleInfo.size;
	}
	
	public int getDownloadRetryCount()
	{
		return HttpDownloadManager.instance.getDownloadTotalConnectCount(downloadRequest);
	}
	
	public int getBadDownloadRetryCount()
	{
		return HttpDownloadManager.instance.getBadDownloadRetryCount(downloadRequest);
	}
	
	public bool isRunning()
	{
		return HttpDownloadManager.instance.isRequestRunning(downloadRequest);
	}
	
	public bool isWaiting()
	{
		return HttpDownloadManager.instance.isRequestWaiting(downloadRequest);
	}
	
	public bool isConnecting()
	{
		return HttpDownloadManager.instance.isRequestConnecting(downloadRequest);
	}
	
	public bool isReadyConnect()
	{
		return HttpDownloadManager.instance.isRequestReadyConnect(downloadRequest);
	}
	
	public DecompressStep getDecompressStep()
	{
		return CompressManager.instance.getDecompressStep(decompressRequest);
	}
	
	public bool isDownloadFailed()
	{
		if(error != DownloadBundleError.None)
		{
			if(needDownload && !downloadFinish)
			{
				return true;
			}
		}
		return false;
	}
	
	public bool isDecompressFailed()
	{
		if(error != DownloadBundleError.None)
		{
			if(!isDownloadFailed())
			{
				return true;
			}
		}
		return false;
	}
	
	public float decompressSpanTime()
	{
		return CompressManager.instance.getSpanTime(decompressRequest);
	}
	
	public void decompress(CompressManager.DecompressCallback callback)
	{
		this.decompressCallBack = callback;
		callback(downloadPath, decompressPath, true);
//		decompressRequest = CompressManager.instance.Decompress (CompressType.NONE, downloadPath, decompressPath, callback);
	}
	
	public void start(HttpRedirectHelper redirectHelper, CallBack callback)
	{
		cancel();

		this.redirectHelper = redirectHelper;
		this.callBack = callback;

		if(needDownload && !downloadFinish)
		{
            this.downloadRequest = HttpDownloadManager.instance.Download(url, bundleInfo.hash, bundleInfo.size, bundleInfo.origin_size, bundleInfo.compress, decompressPath, redirectHelper, HttpDownloadHandler);
		}
		else if(needDecompress && !decompressFinish)
		{
			decompress(DecompressHandler);
		}
//		else if(isLocalDecopmress)
//		{
//			DecompressLocalBundleHelper.instance.DecompressBundle(this.bundleName, this.bundleInfo, DecompressLocalHandler);
//		}
	}

	private void DecompressLocalHandler(bool success)
	{
		if(!success)
		{
			this.error = DownloadBundleError.DecompressFailed;
		}
		else
		{
			downloadFinish = true;
			decompressFinish = true;
		}
		
		CallBack temp2 = callBack;
		callBack = null;
		temp2(this);
	}

	private void HttpDownloadHandler(string url, string localPath, DownloadError status)
	{
		if(status == DownloadError.None)
		{
			downloadFinish = true;
			decompress(DecompressHandler);
		}
		else
		{
			if(status == DownloadError.DownloadSizeError)
			{
				error = DownloadBundleError.DownloadSizeError;
			}
			else if(status == DownloadError.DownloadEncodingError)
			{
				error = DownloadBundleError.DownloadEncodingError;
			}
			else if(status == DownloadError.FileOperationFailed)
			{
				error = DownloadBundleError.FileOperationFailed;
			}
			else if(status == DownloadError.DecompressFailed)
			{
				error = DownloadBundleError.DecompressFailed;
			}
			else
			{
				error = DownloadBundleError.DownloadFailed;
			}
		}

		if(!downloadFinish)
		{
			CallBack temp = callBack;
			callBack = null;
			temp(this);
		}
	}
	
	private void DecompressHandler(string srcPath, string destPath, bool success)
	{
		if(success)
		{
//			CommonUtil.Delete(srcPath);
			decompressFinish = true;
		}
		else
		{
			if(decompressRetryCount < 3/* && SwitchConfig.compileType == CompileType.release*/)
			{
				CommonUtil.Delete(srcPath);

				decompressRetryCount++;

				needDownload = true;
				downloadFinish = false;
                this.downloadRequest = HttpDownloadManager.instance.Download(url, bundleInfo.hash, bundleInfo.size, bundleInfo.origin_size, bundleInfo.compress, decompressPath, redirectHelper, HttpDownloadHandler);
				return;
			}
			else
			{
				error = DownloadBundleError.DecompressFailed;
			}
		}

		CallBack temp2 = callBack;
		callBack = null;
		temp2(this);
	}
	
	public void cancel()
	{
		HttpDownloadManager.instance.Cancel(url, HttpDownloadHandler);
		downloadRequest = null;
		CompressManager.instance.Cancel(downloadPath, decompressPath, this.decompressCallBack);
		decompressRequest = null;
//		DecompressLocalBundleHelper.instance.Cancel(this.bundleName, this.bundleInfo, DecompressLocalHandler);
	}
	
	
}

public class BundleGroupDownloadTask: BundleDownloadManager.DownloadListener
{
	public delegate void DownloadCallback(DownloadBundleError error, bool useDownload);

	protected Dictionary<string, BundleInfo> completeBundleMap = new Dictionary<string, BundleInfo>();
	protected Dictionary<string, DownloadBundleTaskInfo> taskMap = new Dictionary<string, DownloadBundleTaskInfo>();
	int successNum;
	int callBackNum;
	bool isComplete;
	bool isFailed;
	DownloadBundleError error = DownloadBundleError.None;
	DownloadCallback listener;
    uint _noNeedDownloadSize = 0;

    public uint GetNoNeedDownloadSize()
    {
        return _noNeedDownloadSize;
    }

	public DownloadBundleError getError()
	{
		return error;
	}

	protected void setError(DownloadBundleError error)
	{
		this.error = error;
	}

	public bool completed
	{
		get
		{
			return isComplete;
		}

		set
		{
			isComplete = value;
		}
	}

	public bool downloading
	{
		get
		{
			if(completed)
			{
				return false;
			}

			if(taskMap == null)
			{
				return false;
			}

			Dictionary<string, DownloadBundleTaskInfo>.Enumerator e = taskMap.GetEnumerator();
			while(e.MoveNext())
			{
				if(e.Current.Value.isNeedDownload)
				{
					return true;
				}
			}

			return false;
		}
	}
	
	public bool failed
	{
		get
		{
			return isFailed;
		}
	}

	public bool started
	{
		get
		{
			return this.completeBundleMap.Count + this.taskMap.Count > 0;
		}
	}

    public float GetSpeed()
    {
        float speed = 0;

        Dictionary<string, DownloadBundleTaskInfo>.Enumerator e = this.taskMap.GetEnumerator();
        while (e.MoveNext())
        {
            if (!e.Current.Value.isComplete)
            {
                speed += e.Current.Value.getSpeed();
            }
        }

        return speed;
    }
	
	public virtual void Start(string groupName, DownloadCallback listener, bool isGroup = true)
	{
		reset();
		
		this.listener = listener;

		HashSet<string> bundles = new HashSet<string>();
        ConsumeTime.Log("BundleGroupDownloadTask.Start_1", () =>
            {
                if(isGroup)
                {
                    BundleVersionConfig versionConfig = BundleDownloadManager.instance.GetBundleVersionConfig();
                    Dictionary<string, BundleInfo>.Enumerator e = versionConfig.bundles.GetEnumerator();
                    while (e.MoveNext())
                    {
                        bundles.Add(e.Current.Key);
                    }
                }
                else
                {
                    bundles.Add(groupName);
                }
            });
                
        ConsumeTime.Log("BundleGroupDownloadTask.Start_2", () =>
            {
                _noNeedDownloadSize = 0;
                HashSet<string>.Enumerator enumerator = bundles.GetEnumerator();
                while(enumerator.MoveNext())
                {
                    string bundleName = enumerator.Current;
                    float t = Time.realtimeSinceStartup;
                    BundleVersionConfig versionConfig = BundleDownloadManager.instance.GetBundleVersionConfig();
                    BundleInfo info = null;
                    versionConfig.bundles.TryGetValue(bundleName, out info);

                    LocalBundleInfo localBundleInfo = null;
					bool inApp = false;
                    if(BundleVersionManager.instance.isBundleExist(info, out localBundleInfo, out inApp))
                    {
                        _noNeedDownloadSize += info.size;
                        continue;
                    }

                    taskMap.Add(bundleName, null);
                }
            });
	}

    public IEnumerator StartTask()
    {
        int i = 0;
        float sumTime2 = 0;
        Dictionary<string, DownloadBundleTaskInfo> tempMap = new Dictionary<string, DownloadBundleTaskInfo>(taskMap);
        Dictionary<string, DownloadBundleTaskInfo>.Enumerator e2 = tempMap.GetEnumerator();
        while(e2.MoveNext())
        {
            string bundleName = e2.Current.Key;
            float t2 = Time.realtimeSinceStartup;
            DownloadBundleTaskInfo taskInfo = null;
            if(!taskMap.TryGetValue(bundleName, out taskInfo) || taskInfo == null)
            {
                BundleInfo bundleInfo = null;
                taskInfo = BundleDownloadManager.instance.downloadAndDecompressBundle(bundleName, out bundleInfo, this);
                if (taskInfo != null)
                {
                    taskMap[bundleName] = taskInfo;
                }
                else
                {
                    throw new System.Exception("create download task failed for bundle: " + bundleName);
                }

                //                if(bundleInfo != null)
                //                {
                //                    completeBundleMap.Add(bundleName, bundleInfo);
                //                }
            }
            sumTime2 += Time.realtimeSinceStartup - t2;
            i++;

            if (i % 50 == 0)
            {
                yield return null;
            }
        }

//        Debug.Log("consume time: test: " + "  " + sumTime2);


        if(taskMap.Count <= 0)
        {
            onFinish(false);
        }
        //      else
        //      {
        //          DecompressLocalBundleHelper.instance.startDecompress();
        //      }
    }
	
	public void reset()
	{
		error = DownloadBundleError.None;
		isFailed = false;
		isComplete = false;
		callBackNum = 0;
		successNum = 0;
		listener = null;
		
		Dictionary<string, DownloadBundleTaskInfo>.Enumerator enumerator = taskMap.GetEnumerator();
		while(enumerator.MoveNext())
		{
			string bundleName = enumerator.Current.Key;
			BundleDownloadManager.instance.cancel(bundleName, this);
		}
		taskMap.Clear();

		this.completeBundleMap.Clear();
	}
	
	public void onFinishBundle(string bundleName, DownloadBundleTaskInfo info)
	{
		callBackNum++;
		if(info.getError() == DownloadBundleError.None)
		{
			successNum++;
		}
		else
		{
			if(this.error == DownloadBundleError.None)
			{
				this.error = info.getError();
			}

			if(info.getError() == DownloadBundleError.FileOperationFailed)
			{
				Dictionary<string, DownloadBundleTaskInfo>.Enumerator enumerator = taskMap.GetEnumerator();
				while(enumerator.MoveNext())
				{
					enumerator.Current.Value.cancel();
				}

				callBackNum = taskMap.Count;
			}
		}

		if(callBackNum == taskMap.Count)
		{
			if(listener != null)
			{
				bool useNet = false;
				Dictionary<string, DownloadBundleTaskInfo>.Enumerator enumerator = taskMap.GetEnumerator();
				while(enumerator.MoveNext())
				{
					useNet = enumerator.Current.Value.isNeedDownload;
					if(useNet)
					{
						break;
					}
				}
				onFinish(useNet);
			}
		}
	}
	
	private void onFinish(bool useDownload = true)
	{
		isComplete = this.error == DownloadBundleError.None;
		isFailed = !isComplete;
		
		if(listener != null)
		{
			DownloadCallback temp = listener;
			listener = null;
			temp(this.error, useDownload);
		}
	}
	
	public void getProgress(ref uint total, ref uint progress, bool isAll = true, bool onlyDownload = false)
	{
		total = 0;
		progress = 0;
		
		Dictionary<string, DownloadBundleTaskInfo>.Enumerator enumerator = taskMap.GetEnumerator();
		while(enumerator.MoveNext())
		{
			DownloadBundleTaskInfo taskInfo = enumerator.Current.Value;
            if (taskInfo == null)
            {
                total += BundleDownloadManager.instance.GetBundleVersionConfig().bundles[enumerator.Current.Key].size;
                continue;
            }

			if(taskInfo.isLocalDecopmress)
			{
				if(!onlyDownload)
				{
					total += taskInfo.size;
					int downloadProgress = taskInfo.getProgress();
					progress += (uint)downloadProgress;
				}
			}
			else
			{
				if(taskInfo.isNeedDownload)
				{
					total += taskInfo.size;
					int downloadProgress = taskInfo.getProgress();
					progress += (uint)downloadProgress;
				}
				
				if(taskInfo.isNeedDecompress)
				{
					total += 10;
					if(taskInfo.getDecompressStep() == DecompressStep.decompressed)
					{
						progress += 10;
					}
				}
			}
		}
		
		if(isAll)
		{
			Dictionary<string, BundleInfo>.Enumerator enumerator2 = completeBundleMap.GetEnumerator();
			while(enumerator2.MoveNext())
			{
				total += enumerator2.Current.Value.size;
				progress += enumerator2.Current.Value.size;
			}
		}
	}
	
	public Dictionary<string, DownloadBundleTaskInfo> getDownloadTaskInfos()
	{
		return taskMap;
	}

	public Dictionary<string, BundleInfo> getCompleteBundleInfos()
	{
		return completeBundleMap;
	}
}

struct CodeVersionInfo
{
	public int app_build_version;
	public ulong app_build_time;
	public uint res_config_crc;
	public int code_file_num;
}

//public class CodeBundleGroupDownloadTask: BundleGroupDownloadTask
//{
//	private DownloadCallback backupListener;
//	private bool _isNewCode;
//	private string codeDir;
//	private string codeDir2;
//	private string codeTempDir;
//	private string codeVersionInfoFileName = "code_version.txt";
//
//	public bool isNewCode
//	{
//		get
//		{
//			return _isNewCode;
//		}
//	}
//	
//	public override void start(string groupName, DownloadCallback listener, bool isGroup = true)
//	{
//		if(codeDir == null)
//		{
//			codeDir = Path.GetDirectoryName(CommonUtil.cachePath) + "/deploy_res";
//			codeDir2 = Path.GetDirectoryName(CommonUtil.cachePath) + "/deploy_res_";
//			codeTempDir = Path.GetDirectoryName(CommonUtil.cachePath) + "/deploy_res_temp";
//		}
//
//		this.backupListener = listener;
//		base.start(groupName, DownloadCallBack, isGroup);
//	}
//
//	public void DownloadCallBack(DownloadBundleError error, bool useNet)
//	{
//		if(error == DownloadBundleError.None)
//		{
//			if(SwitchConfig.isEnableDownloadBundle)
//			{
//				string str = CommonUtil.fileToString(codeDir + "/" + codeVersionInfoFileName);
//				CodeVersionInfo oldVersionInfo = new CodeVersionInfo();
//				if(str != null)
//				{
//					oldVersionInfo = JsonConvert.DeserializeObject<CodeVersionInfo>(str);
//				}
//
//				BundleVersionConfig versionConfig = BundleVersionManager.instance.GetBundleVersionConfig();
//				if(oldVersionInfo.app_build_time != Version.build_time || oldVersionInfo.app_build_version != Version.build_version || oldVersionInfo.res_config_crc != versionConfig.crc)
//				{
//					HashSet<string> codeBundles = new HashSet<string>(this.completeBundleMap.Keys);
//					foreach(string bundleName in this.taskMap.Keys)
//					{
//						codeBundles.Add(bundleName);
//					}
//
//					CommonUtil.Delete(codeTempDir);
//
//					int copiedFileNum = 0;
//					bool copySuccess = true;
//					foreach(string bundleName in codeBundles)
//					{
//						ExistBundleInfo info2 = BundleVersionManager.instance.getExistBundleInfo(bundleName);
//
//						string destPath = codeTempDir + "/" + bundleName[0] + "/" + bundleName;
//						if(info2 != null)
//						{
//							string bundlePath = BundleVersionManager.bundlePath + "/" + info2.fileName + BundleVersionManager.bundleExt2;
//							if(File.Exists(bundlePath))
//							{
//								long fileSize = CommonUtil.GetFileSize(bundlePath);
//								if(fileSize > 0)
//								{
//									if(!CommonUtil.Copy(bundlePath, destPath))
//									{
//										error = DownloadBundleError.FileOperationFailed;
//										this.setError(DownloadBundleError.FileOperationFailed);
//										copySuccess = false;
//										break;
//									}
//
//									copiedFileNum++;
//								}
//							}
//							else
//							{
//								CommonUtil.Delete(destPath);
//							}
//						}
//						else
//						{
//							CommonUtil.Delete(destPath);
//						}
//					}
//
//					if(copySuccess)
//					{
//						CodeVersionInfo newVersionInfo = new CodeVersionInfo();
//						newVersionInfo.app_build_version = Version.build_version;
//						newVersionInfo.app_build_time = Version.build_time;
//						newVersionInfo.res_config_crc = versionConfig.crc;
//						newVersionInfo.code_file_num = copiedFileNum;
//						string str2 = JsonConvert.SerializeObject(newVersionInfo, Formatting.Indented);
//						if(CommonUtil.stringToFile(codeTempDir + "/" + codeVersionInfoFileName, str2))
//						{
//							string destDir = codeDir2;
//							if(copiedFileNum <= 0 && oldVersionInfo.code_file_num <= 0)
//							{
//								destDir = codeDir;
//							}
//
//							if(CommonUtil.Move(codeTempDir, destDir))
//							{
//								if(copiedFileNum > 0 || oldVersionInfo.code_file_num > 0)
//								{
//									_isNewCode = true;
//								}
//							}
//							else
//							{
//								error = DownloadBundleError.FileOperationFailed;
//								this.setError(DownloadBundleError.FileOperationFailed);
//							}
//						}
//						else
//						{
//							error = DownloadBundleError.FileOperationFailed;
//							this.setError(DownloadBundleError.FileOperationFailed);
//						}
//					}
//				}
//			}
//			else
//			{
//				if(Directory.Exists(codeDir))
//				{
//					CommonUtil.Delete(codeDir);
//					_isNewCode = true;
//				}
//			}
//		}
//
//		DownloadCallback temp = backupListener;
//		backupListener = null;
//		temp(error, useNet);
//	}
//}



public class BundleDownloadManager: Singleton<BundleDownloadManager>
{
//	HttpRedirectHelper redirectionHelper = new BundleHttpRedirectHelper();
    HttpRedirectHelper redirectionHelper = null;

	public interface DownloadListener
	{
		void onFinishBundle(string bundleName, DownloadBundleTaskInfo info);
	}
	
	private class TaskInfo
	{
		public DownloadBundleTaskInfo info;
		public HashSet<DownloadListener> callBackSet = new HashSet<DownloadListener>();
	}
	
	private readonly bool enableLog = false;
	private string _downloadUrl;
	private Dictionary<string, TaskInfo> taskMap = new Dictionary<string, TaskInfo>();
	HashSet<string> allLocalBundleSet;
//	BundleVersionConfig localBundleVersionConfig;
    BundleVersionConfig bundleVersionConfig;

	public void delTempFiles()
	{
		if(!Directory.Exists(BundleVersionManager.downloadPath))
		{
			return;
		}
		
		string[] paths = Directory.GetFiles(BundleVersionManager.downloadPath, "*", SearchOption.AllDirectories);
		for(int i = 0; i < paths.Length; i++)
		{
			CommonUtil.Delete(paths[i]);
		}
	}
	
	public void cancel(string bundleName, DownloadListener listener)
	{
		TaskInfo taskInfo = null;
		if(taskMap.TryGetValue(bundleName, out taskInfo))
		{
			taskInfo.callBackSet.Remove(listener);
			if(taskInfo.callBackSet.Count <= 0)
			{
				taskMap.Remove(bundleName);
				taskInfo.info.cancel();
			}
		}
	}
	
	public string GetBundleDownloadUrl()
	{
		return this._downloadUrl;
	}
	
	public BundleVersionConfig GetBundleVersionConfig()
	{
        return this.bundleVersionConfig;
	}
	
	public void SetBundleVersionConfig(BundleVersionConfig config)
	{
        this.bundleVersionConfig = config;
	}
	
	public static BundleVersionConfig ConvertToBundleVersionConfig(string config)
	{
		if(!string.IsNullOrEmpty(config))
		{
			try
			{
				BundleVersionConfig tempConfig = null;
				tempConfig = JsonConvert.DeserializeObject<BundleVersionConfig>(config);
				return tempConfig;
			}
			catch(System.Exception e)
			{
				Debug.LogWarning(e);
			}
		}
		
		return null;
	}

	public static BundleCompleteInfo ConvertToCompleteInfo(string config)
	{
		if(!string.IsNullOrEmpty(config))
		{
			try
			{
				BundleCompleteInfo tempConfig = null;
				tempConfig = JsonConvert.DeserializeObject<BundleCompleteInfo>(config);
				return tempConfig;
			}
			catch(System.Exception e)
			{
				Debug.LogWarning(e);
			}
		}
		
		return null;
	}

//	public static BundleInfo convertToBundleInfo (string str)
//	{
//		if(!string.IsNullOrEmpty(str))
//		{
//			BundleInfo info = null;
//			try
//			{
//				info = JsonConvert.DeserializeObject<BundleInfo> (str);
//				return info;
//			}
//			catch(System.Exception e)
//			{
//				Debug.LogWarning(e);
//			}
//		}
//		return null;
//	}
	
    public void SetUrl(string url)
    {
        this._downloadUrl = url;
    }

    public void SetRedirectHelper(HttpRedirectHelper redirectHelper)
    {
        this.redirectionHelper = redirectHelper;
    }

//	public bool setBundleVersionConfig(BundleVersionConfig newConfig, string configStr, string url = null)
//	{
//		if (!SwitchConfig.isEnableDownloadBundle)
//		{
//			return true;
//		}
//		
//		if (!string.IsNullOrEmpty(url))
//		{
//			this._downloadUrl = url;
//		}
//		
//		if(newConfig != null)
//		{
//			if(configStr == null)
//			{
//				configStr = JsonConvert.SerializeObject(newConfig, Formatting.Indented);
//			}
//			
//			if(!CommonUtil.stringToFile(BundleVersionManager.bundlePath + "/" + BundleVersionManager.configName, configStr))
//			{
//				return false;
//			}
//			this.setBundleVersionConfig(newConfig);
//
//            CommonUtil.stringToFile(BundleVersionManager.bundlePath + "/" + BundleVersionManager.crcConfigName, newConfig.md5);
//		}
//
//		return true;
//	}

	
	public DownloadBundleTaskInfo downloadAndDecompressBundle(string bundleName, out BundleInfo bundleInfo, DownloadListener callBack)
	{
		bundleInfo = null;
		GetBundleVersionConfig().bundles.TryGetValue(bundleName, out bundleInfo);
		
		if(bundleInfo == null)
		{
			return null;
		}
		
		TaskInfo info = null;
		if(!taskMap.TryGetValue(bundleName, out info))
		{
			DownloadBundleTaskInfo task = createTask(bundleName, bundleInfo);
			if(task == null)
			{
				return null;
			}
			else
			{
				info = new TaskInfo();
				info.info = task;
				taskMap.Add(bundleName, info);
				info.info.start(redirectionHelper, processBundleCallback);
			}
		}
		
		info.callBackSet.Add(callBack);
		
		return info.info;
	}
	
	private void processBundleCallback(DownloadBundleTaskInfo info)
	{
		string bundleName = info.getBundleName();
		TaskInfo taskInfo = null;
		if(taskMap.TryGetValue(bundleName, out taskInfo))
		{
			taskMap.Remove(bundleName);

//			if(taskInfo.info.isComplete)
//			{
//				BundleVersionManager.instance.addExistBundle(bundleName);
//			}

			HashSet<DownloadListener> temp = new HashSet<DownloadListener>(taskInfo.callBackSet);
			taskInfo.callBackSet.Clear();
			
			HashSet<DownloadListener>.Enumerator enumerator = temp.GetEnumerator();
			while(enumerator.MoveNext())
			{
				enumerator.Current.onFinishBundle(bundleName, info);
			}
		}
	}

	private bool useLocal(string bundleName, BundleInfo info)
	{
//		#if UNITY_ANDROID && !UNITY_EDITOR
//		if(allLocalBundleSet == null)
//		{
//			string str = ChatPluginAndroid.Instance.AssetToString(BundleVersionManager.allLocalBundleConfigName);
//			if(str != null)
//			{
//				allLocalBundleSet = JsonConvert.DeserializeObject<HashSet<string>>(str);
//				
//				string str2 = ChatPluginAndroid.Instance.AssetToString(BundleVersionManager.configName);
//				if(str2 != null)
//				{
//					localBundleVersionConfig = BundleDownloadManager.ConvertToBundleVersionConfig(str2);
//				}
//			}
//			else
//			{
//				allLocalBundleSet = new HashSet<string>();
//			}
//		}
//		#endif
		
//		if(localBundleVersionConfig != null && allLocalBundleSet != null && allLocalBundleSet.Contains(bundleName))
//		{
//			BundleInfo info2 = null;
//			if(localBundleVersionConfig.bundles.TryGetValue(bundleName, out info2))
//			{
//                if(info2.hash == info.hash)
//				{
//					return true;
//				}
//			}
//		}

		return false;
	}
	
	private DownloadBundleTaskInfo createTask(string bundleName, BundleInfo info)
	{
		bool needDownload = true;
		bool needDecompress = true;
		BundleInfo versionConfig = null;
//		ExistBundleInfo info2 = BundleVersionManager.instance.getExistBundleInfo(bundleName);
//		if(info2 != null)
//		{
//            if(info2.hash == info.hash)
//			{
//				needDownload = false;
//				needDecompress = false;
//			}
//		}

        string bundleFile = BundleVersionManager.bundlePath + "/" + info.GetHashName() + BundleVersionManager.bundleExt2;

		if(needDownload || needDecompress)
		{
            string downloadBundleFile = BundleVersionManager.downloadPath + "/" + info.GetHashName() + BundleVersionManager.bundleExt2;
//			if(File.Exists(downloadBundleFile))
//			{
//				if(true/* && SwitchConfig.compileType == CompileType.release*/)
//				{
//
//				}
//				else
//				{
//					needDownload = false;
//				}
//			}

//			if(needDownload)
//			{
//				CommonUtil.Delete(bundleFile);
//			}
		}

		Bundle bundle = null;
//		BundleConfig config = BundleManager.instance.getConfig();
//		if(config != null)
//		{
//			bundle = config.getBundle(bundleName);
//		}

		if(needDownload || needDecompress)
		{
			if(useLocal(bundleName, info))
			{
				needDownload = false;
				needDecompress = false;

				if(bundle != null && bundle.type == BundleType.code)
				{
					CommonUtil.Delete(bundleFile);
					return null;
				}
			}

			DownloadBundleTaskInfo taskInfo = new DownloadBundleTaskInfo(bundleName, info, _downloadUrl, needDownload, needDecompress);
			return taskInfo;
		}
		else
		{
			if(bundle != null && bundle.type == BundleType.code)
			{
				if(useLocal(bundleName, info))
				{
					CommonUtil.Delete(bundleFile);
				}
			}
		}
		
		return null;
	}
}
